package com.jzo2o.foundations.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.foundations.constants.RedisConstants;
import com.jzo2o.foundations.mapper.RegionMapper;
import com.jzo2o.foundations.mapper.ServeItemMapper;
import com.jzo2o.foundations.mapper.ServeMapper;
import com.jzo2o.foundations.model.domain.Region;
import com.jzo2o.foundations.model.domain.Serve;
import com.jzo2o.foundations.model.domain.ServeItem;
import com.jzo2o.foundations.model.dto.request.ServePageQueryReqDTO;
import com.jzo2o.foundations.model.dto.request.ServeUpsertReqDTO;
import com.jzo2o.foundations.model.dto.response.*;
import com.jzo2o.foundations.service.IServeService;
import com.jzo2o.mysql.utils.PageHelperUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 区域管理
 *
 * @author itcast
 * @create 2023/7/17 16:50
 **/
@Service
public class ServeServiceImpl extends ServiceImpl<ServeMapper, Serve> implements IServeService {
    @Autowired
    private ServeItemMapper serveItemMapper;
    @Autowired
    private RegionMapper regionMapper;
    @Autowired
    private ServeMapper serveMapper;

    /**
     * 区域服务分页查询
     *
     * @param servePageQueryReqDTO 前端传来查询信息
     * @return 区域服务信息
     */
    @Override
    public PageResult<ServeResDTO> findByPage(ServePageQueryReqDTO servePageQueryReqDTO) {
        return PageHelperUtils.selectPage(servePageQueryReqDTO, () -> baseMapper.queryServePage(servePageQueryReqDTO.getRegionId()));
    }

    /**
     * 区域服务新增
     *
     * @param serveUpsertReqDTOS 前端传来的新增服务的信息
     */
    @Override
    public void addBatch(List<ServeUpsertReqDTO> serveUpsertReqDTOS) {
        //遍历集合
        for (ServeUpsertReqDTO dto : serveUpsertReqDTOS) {
            //1. 服务项目必须是启用状态的才能添加到区域
            ServeItem serveItem = serveItemMapper.selectById(dto.getServeItemId());
            if (ObjectUtil.isEmpty(serveItem)) {
                throw new ForbiddenOperationException("服务项目不存在！");
            }
            if (serveItem.getActiveStatus() != 2) {
                throw new ForbiddenOperationException(" 服务项目必须是启用状态!");
            }
            //2. 一个服务项目对于一个区域，只能添加一次
            Integer count = baseMapper.selectCount(Wrappers.<Serve>lambdaQuery()
                    .eq(Serve::getServeItemId, dto.getServeItemId())
                    .eq(Serve::getRegionId, dto.getRegionId())
            );
            if (count > 0) {
                throw new ForbiddenOperationException(" 一个服务项目对于一个区域，只能添加一次!");
            }
            //3.信息拷贝
            Serve serve = BeanUtil.toBean(dto, Serve.class);
            //4.查询cityCode
            Region region = regionMapper.selectById(dto.getRegionId());
            if (ObjectUtil.isEmpty(region)) {
                throw new ForbiddenOperationException("该区域不存在！");
            }
            serve.setCityCode(region.getCityCode());
            //5.保存到数据库
            baseMapper.insert(serve);
        }

    }

    /**
     * 区域服务删除
     *
     * @param id 服务id
     */
    @Override
    public void deleteById(Long id) {
        //1、根据ID查询出服务的状态
        Serve serve = baseMapper.selectById(id);
        if (ObjectUtil.isEmpty(serve)) {
            throw new ForbiddenOperationException("该服务不存在!");
        }
        //2.要求当状态为草稿状态方可删除
        if (serve.getSaleStatus() != 0) {
            throw new ForbiddenOperationException("删除失败, 当前区域服务不是草稿状态");
        }
        //3、删除
        baseMapper.deleteById(id);
    }

    /**
     * 区域服务修改价格
     *
     * @param id 服务id
     */
    @Override
    public void updateOnSale(Long id) {
        Serve serve = baseMapper.selectById(id);
        if (ObjectUtil.isEmpty(serve)) {
            throw new ForbiddenOperationException("该服务不存在！");
        }
        //1) 区域服务当前非上架状态
        if (serve.getSaleStatus() == 2) {
            throw new ForbiddenOperationException("当前服务为上架状态");
        }
        //2) 服务项目是启用状态
        ServeItem serveItem = serveItemMapper.selectById(serve.getServeItemId());
        if (ObjectUtil.isEmpty(serveItem)) {
            throw new ForbiddenOperationException("该服务项目不存在！");
        }
        if (serveItem.getActiveStatus() != 2) {
            throw new ForbiddenOperationException(" 服务项目不是启用状态！");
        }
        serve.setSaleStatus(2);
        baseMapper.updateById(serve);
    }

    /**
     * 区域服务下架
     *
     * @param id 服务id
     */
    @Override
    public void updateOffSale(Long id) {
        Serve serve = baseMapper.selectById(id);
        if (ObjectUtil.isEmpty(serve)) {
            throw new ForbiddenOperationException("该服务不存在！");
        }
        //下架成功的必要条件是区域服务当前为上架状
        if (serve.getSaleStatus() != 2) {
            throw new ForbiddenOperationException("下架失败,区域服务当前不是上架状态！");
        }
        serve.setSaleStatus(1);
        baseMapper.updateById(serve);
    }

    /**
     * 区域服务设置热门
     *
     * @param id
     */
    @Override
    public void updateOnHot(Long id) {
        Serve serve = baseMapper.selectById(id);
        if (ObjectUtil.isEmpty(serve)) {
            throw new ForbiddenOperationException("该服务不存在!");
        }
        serve.setIsHot(1);
        serve.setHotTimeStamp(System.currentTimeMillis());
        baseMapper.updateById(serve);

    }

    /**
     * 区域服务取消热门
     *
     * @param id 服务id
     */
    @Override
    public void updateOffHot(Long id) {
        Serve serve = baseMapper.selectById(id);
        if (ObjectUtil.isEmpty(serve)) {
            throw new ForbiddenOperationException("该服务不存在!");
        }
        serve.setIsHot(0);
        serve.setHotTimeStamp(System.currentTimeMillis());
        baseMapper.updateById(serve);
    }

    /**
     * 服务列表
     *
     * @param regionId 区域id
     * @return 服务列表
     */
    @Caching(
            cacheable = {
                    //返回数据为空，则缓存空值30分钟，这样可以避免缓存穿透
                    @Cacheable(value = RedisConstants.CacheName.SERVE_ICON, key ="#regionId" ,
                            unless ="#result.size() > 0",cacheManager = RedisConstants.CacheManager.THIRTY_MINUTES),

                    //返回值不为空，则永久缓存数据
                    @Cacheable(value = RedisConstants.CacheName.SERVE_ICON, key ="#regionId" ,
                            unless ="#result.size() == 0",cacheManager = RedisConstants.CacheManager.FOREVER)
            }
    )
    @Override
    public List<ServeCategoryResDTO> fiandServeList(Long regionId) {
        //1、检查参数
        Region region = regionMapper.selectById(regionId);
        if (ObjectUtil.isEmpty(region) || region.getActiveStatus() != 2) {
            throw new ForbiddenOperationException("该区域不存在");
        }
        //2、查询服务列表信息
        List<ServeCategoryResDTO> list = serveMapper.fiandServeList(regionId);
        //展示两个服务分类（升序取前两个），每个服务分类下展示4个服务项（升序取前4个）
        //3、截取前俩个服务分类
        List<ServeCategoryResDTO> dtoList = CollectionUtil.sub(list, 0, Math.min(list.size(), 2));
        //4、在截取的俩个服务分类中截取前4个服务项
        dtoList.forEach(dto -> {
            List<ServeSimpleResDTO> serveResDTOList = dto.getServeResDTOList();
            //截取前4个服务项
            List<ServeSimpleResDTO> dtos = CollectionUtil.sub(serveResDTOList, 0, Math.min(serveResDTOList.size(), 4));
            dto.setServeResDTOList(dtos);
        });
        return dtoList;
    }

    /**
     * 精选推荐
     *
     * @param regionId 区域id
     * @return 精选推荐列表
     */
    @Caching(
            cacheable = {
                    //返回数据为空，则缓存空值30分钟，这样可以避免缓存穿透
                    @Cacheable(value = RedisConstants.CacheName.HOT_SERVE,key ="#regionId" ,
                            unless ="#result.size() > 0",cacheManager = RedisConstants.CacheManager.THIRTY_MINUTES),

                    //返回值不为空，则永久缓存数据
                    @Cacheable(value = RedisConstants.CacheName.HOT_SERVE,key ="#regionId" ,
                            unless ="#result.size() == 0",cacheManager = RedisConstants.CacheManager.FOREVER)
            }
    )
    @Override
    public List<ServeAggregationSimpleResDTO> findHotServeList(Long regionId) {
        //1、检查参数
        Region region = regionMapper.selectById(regionId);
        if (ObjectUtil.isEmpty(region) || region.getActiveStatus() != 2) {
            throw new ForbiddenOperationException("该区域不存在");
        }
        //2、查询热门精选推荐列表
        return baseMapper.findHotServeList(regionId);
    }

    /**
     * 查询服务详情
     *
     * @param id 服务id
     * @return 查询服务详情
     */
    @Override
    public ServeAggregationSimpleResDTO serveDetails(Long id) {
        //1、检查参数
        Serve serve = baseMapper.selectById(id);
        if (ObjectUtil.isEmpty(serve) || serve.getSaleStatus() != 2) {
            throw new ForbiddenOperationException("该服务不存在或服务未上架！");
        }
        //2、查询服务详情
        return baseMapper.serveDetails(id);
    }

    /**
     * 查询当前区域下上架服务对应的分类
     *
     * @param regionId 区域id
     * @return 服务对应的分类
     */
    @Override
    public List<ServeAggregationTypeSimpleResDTO> serveTypeList(Long regionId) {
        //1、检查参数
        Region region = regionMapper.selectById(regionId);
        if (ObjectUtil.isEmpty(region) || region.getActiveStatus() != 2) {
            throw new ForbiddenOperationException("该区域不存在");
        }
        //2、查询当前区域下上架服务对应的分类
        List<ServeAggregationTypeSimpleResDTO> list = baseMapper.serveTypeList(regionId);
        return list;
    }
}
